home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2000 February / Macworld (2000-02).dmg / Cool Extras! / WallBall Screen Saver / WallBall.dxr / 00052_Random Movement and Rotation.ls < prev    next >
Encoding:
Text File  |  1999-11-11  |  8.1 KB  |  208 lines

  1. property pSprite, pCenterOffset, pLimits, pLimitsOrigin, pPath, pMovePeriod, pMoveStart, pMoveEnd, pRotate, pRotateStart, pRotatePeriod, pRotateEnd, pLimitsLeft, pLimitsRight, pLimitsTop, pLimitsBottom, pSpeed, pRotationSpeed, pLoopiness, pWackiness
  2.  
  3. on getBehaviorDescription
  4.   vDesc = "RANDOM MOVEMENT & ROTATION" & RETURN & RETURN
  5.   vDesc = vDesc & "Sprite will move randomly within defined area, spinning"
  6.   vDesc = vDesc && "wildly if so desired. Author can control both the speed of"
  7.   vDesc = vDesc && "the movement and speed of rotation, as well as how radically"
  8.   vDesc = vDesc && "the movement and rotation vary. Default movement limit"
  9.   vDesc = vDesc && "is the stage area." & RETURN & RETURN
  10.   vDesc = vDesc & "PERMITTED MEMBER TYPES:" & RETURN & mPermittedMemberTypes()
  11.   vDesc = vDesc & RETURN & RETURN & "PARAMETERS:" & RETURN
  12.   vDesc = vDesc & " - Horizontal and vertical coordinates for movement limits"
  13.   vDesc = vDesc & RETURN & " - Average speed in pixels/second" & RETURN
  14.   vDesc = vDesc & " - Loopiness modifies how close the sprite's path is to"
  15.   vDesc = vDesc && "a straight line." & RETURN
  16.   vDesc = vDesc & " - Rotation speed determines how fast sprite rotates;"
  17.   vDesc = vDesc && "1000 = 360 degrees/second" & RETURN
  18.   vDesc = vDesc & " - Wackiness controls how much the rotation of the"
  19.   vDesc = vDesc & "sprite may vary before changing direction."
  20.   return vDesc
  21. end
  22.  
  23. on getBehaviorTooltip me
  24.   vTip = "Animate a sprite along a random path" & RETURN
  25.   vTip = vTip & "and determine its motion and speed" & RETURN
  26.   vTip = vTip & "while it is animating."
  27.   return vTip
  28. end
  29.  
  30. on beginSprite me
  31.   mInitialize(me)
  32. end
  33.  
  34. on prepareFrame me
  35.   mUpdate(me)
  36. end
  37.  
  38. on mInitialize me
  39.   pSprite = sprite(me.spriteNum)
  40.   vMember = pSprite.member
  41.   if not getPos(mPermittedMemberTypes(), vMember.type) then
  42.     alert("Sprite" && pSprite.spriteNum & ": 'Random Movement & Rotation' works with" && mPermittedMemberTypes() && "cast members,")
  43.   end if
  44.   case vMember.type of
  45.     #animgif, #flash, #quickTimeMedia, #digitalVideo, #vectorShape:
  46.       if vMember.directToStage then
  47.         alert("Sprite" && pSprite.spriteNum & ": Direct To Stage media may cause" && "playback problems with the 'Random Movement & Rotation' behavior.")
  48.       end if
  49.   end case
  50.   if pRotationSpeed > 0 then
  51.     case vMember.type of
  52.       #field, #picture:
  53.         pRotationSpeed = 0
  54.         alert("Sprite" && pSprite.spriteNum & ": 'Random Movement & Rotation' behavior cannot rotate #field or #picture" && "sprites. Set the Rotation Speed parameter for this sprite to 0" && "to prevent this dialog appearing")
  55.     end case
  56.   end if
  57.   vRect = pSprite.rect
  58.   vHalfHeight = vRect.height / 2
  59.   vHalfWidth = vRect.width / 2
  60.   vMaxDimension = max(vHalfHeight, vHalfWidth)
  61.   vFarCorner = max(mVectorLength(pSprite.loc - point(vRect.left, vRect.top)), mVectorLength(pSprite.loc - point(vRect.right, vRect.top)), mVectorLength(pSprite.loc - point(vRect.left, vRect.bottom)), mVectorLength(pSprite.loc - point(vRect.right, vRect.bottom)))
  62.   vCenter = point(vHalfWidth, vHalfHeight) + point(vRect.left, vRect.top)
  63.   pCenterOffset = vCenter - pSprite.loc
  64.   pLimits = rect(pLimitsLeft, pLimitsTop, pLimitsRight, pLimitsBottom)
  65.   pLimits = pLimits + rect(vFarCorner, vFarCorner, -vFarCorner, -vFarCorner)
  66.   if (pLimits.width < vRect.width) or (pLimits.height < vRect.height) then
  67.     alert("Sprite" && pSprite.spriteNum & ": 'Random Movement & Rotation' behavior movement limitations" && "are too small to allow for full rotation of sprite.")
  68.   end if
  69.   pLimitsOrigin = point(pLimits.left, pLimits.top)
  70.   mNewPath(me)
  71.   mNewRotation(me)
  72. end
  73.  
  74. on mUpdate me
  75.   vTime = the milliSeconds
  76.   mMove(me, vTime)
  77.   mRotate(me, vTime)
  78. end
  79.  
  80. on mMove me, vTime
  81.   if pSpeed then
  82.     if vTime < pMoveEnd then
  83.       vElapsed = vTime - pMoveStart
  84.       if vElapsed > 0 then
  85.         vT1 = float(vElapsed) / pMovePeriod
  86.         vT2 = vT1 * vT1
  87.         vT3 = vT2 * vT1
  88.         vNewPosition = pPath.p0
  89.         vModPoint = pPath.dc * vT1
  90.         vNewPosition = vNewPosition + vModPoint
  91.         vModPoint = pPath.db * vT2
  92.         vNewPosition = vNewPosition + vModPoint
  93.         vModPoint = pPath.da * vT3
  94.         vNewPosition = vNewPosition + vModPoint
  95.         pSprite.loc = vNewPosition
  96.       end if
  97.     else
  98.       pSprite.loc = pPath.p3
  99.       mNewPath(me)
  100.     end if
  101.   end if
  102. end
  103.  
  104. on mRotate me, vTime
  105.   if pRotationSpeed then
  106.     if vTime < pRotateEnd then
  107.       vElapsed = vTime - pRotateStart
  108.       if vElapsed > 0 then
  109.         vRotation = pRotate.start + (pRotate.diff * vElapsed / pRotatePeriod)
  110.         pSprite.rotation = vRotation
  111.       end if
  112.     else
  113.       pSprite.rotation = pRotate.end
  114.       mNewRotation(me)
  115.     end if
  116.   end if
  117. end
  118.  
  119. on mNewPath me
  120.   if voidp(pPath) then
  121.     pPath = [#p0: pSprite.loc, #p1: pSprite.loc, #p2: pSprite.loc, #p3: pSprite.loc]
  122.   end if
  123.   if pSpeed then
  124.     vDest = point(random(pLimits.width), random(pLimits.height)) + pLimitsOrigin
  125.     vP0 = pPath.p3
  126.     vVector = vDest - vP0
  127.     vVectorLen = mVectorLength(vVector)
  128.     vLoopiness = vVectorLen * pLoopiness / 25
  129.     vP1 = mRestrain(vP0 + (pPath.p3 - pPath.p2), pLimits)
  130.     if vLoopiness then
  131.       vRandomPoint = point(mRandomSign() * random(vLoopiness), mRandomSign() * random(vLoopiness))
  132.     else
  133.       vRandomPoint = point(0, 0)
  134.     end if
  135.     vP2 = mRestrain(vP0 + (vVector * 2 / 3) + vRandomPoint, pLimits)
  136.     pPath = [#p0: vP0, #p1: vP1, #p2: vP2, #p3: vDest]
  137.     setaProp(pPath, #dc, 3 * (pPath.p1 - pPath.p0))
  138.     setaProp(pPath, #db, (3 * (pPath.p2 - pPath.p1)) - pPath.dc)
  139.     setaProp(pPath, #da, pPath.p3 - pPath.p0 - pPath.dc - pPath.db)
  140.     vDistance = mVectorLength(pPath.p0 - pPath.p1) + mVectorLength(pPath.p1 - pPath.p2) + mVectorLength(pPath.p2 - pPath.p3)
  141.     pMovePeriod = vDistance * 1000 / pSpeed
  142.     pMoveStart = the milliSeconds
  143.     pMoveEnd = pMoveStart + pMovePeriod
  144.   end if
  145. end
  146.  
  147. on mNewRotation me
  148.   if voidp(pRotate) then
  149.     pRotate = [#start: 0, #end: 0, #diff: 0]
  150.   end if
  151.   if pRotationSpeed then
  152.     vRotation = pSprite.rotation
  153.     if pRotate.diff < 0 then
  154.       vOffset = random(pWackiness)
  155.     else
  156.       vOffset = -random(pWackiness)
  157.     end if
  158.     vTargetRotation = vRotation + vOffset
  159.     pRotateStart = the milliSeconds
  160.     pRotatePeriod = abs(vOffset) * 1000 / pRotationSpeed * 1000 / 360
  161.     pRotateEnd = pRotateStart + pRotatePeriod
  162.     pRotate = [#start: vRotation, #end: vTargetRotation, #diff: vOffset]
  163.   end if
  164. end
  165.  
  166. on mVectorLength vVector
  167.   vSquare = (vVector.locH * vVector.locH) + (vVector.locV * vVector.locV)
  168.   return sqrt(vSquare)
  169. end
  170.  
  171. on mRandomSign
  172.   return (random(2) * 2) - 3
  173. end
  174.  
  175. on mRestrain vPoint, vRect
  176.   vPoint.locH = max(vRect.left, min(vRect.right, vPoint.locH))
  177.   vPoint.locV = max(vRect.top, min(vRect.bottom, vPoint.locV))
  178.   return vPoint
  179. end
  180.  
  181. on getPropertyDescriptionList me
  182.   if not (the currentSpriteNum) then
  183.     exit
  184.   end if
  185.   vRect = (the stage).rect
  186.   vMemberType = sprite(the currentSpriteNum).member.type
  187.   case vMemberType of
  188.     #text, #picture:
  189.       vRotateSpeed = 0
  190.     otherwise:
  191.       vRotateSpeed = 100
  192.   end case
  193.   vPDList = [:]
  194.   setaProp(vPDList, #pLimitsLeft, [#comment: "Limit of movement (left)", #format: #integer, #default: 0, #range: [#min: 0, #max: vRect.width]])
  195.   setaProp(vPDList, #pLimitsTop, [#comment: "Limit of movement (top)", #format: #integer, #default: 0, #range: [#min: 0, #max: vRect.height]])
  196.   setaProp(vPDList, #pLimitsRight, [#comment: "Limit of movement (right)", #format: #integer, #default: vRect.width, #range: [#min: 0, #max: vRect.width]])
  197.   setaProp(vPDList, #pLimitsBottom, [#comment: "Limit of movement (bottom)", #format: #integer, #default: vRect.height, #range: [#min: 0, #max: (the stage).rect.height]])
  198.   setaProp(vPDList, #pSpeed, [#comment: "Speed of movement", #format: #integer, #default: 100, #range: [#min: 0, #max: 1000]])
  199.   setaProp(vPDList, #pLoopiness, [#comment: "Loopiness", #format: #integer, #default: 10, #range: [#min: 0, #max: 25]])
  200.   setaProp(vPDList, #pRotationSpeed, [#comment: "Speed of rotation", #format: #integer, #default: vRotateSpeed, #range: [#min: 0, #max: 1000]])
  201.   setaProp(vPDList, #pWackiness, [#comment: "Wackiness", #format: #integer, #default: 120, #range: [#min: 0, #max: 360]])
  202.   return vPDList
  203. end
  204.  
  205. on mPermittedMemberTypes me
  206.   return [#bitmap, #flash, #picture, #field, #text, #vectorShape, #animgif]
  207. end
  208.